(function ($) {
    $.fn.yqFileEdit = function (opts, param) {
        if (typeof opts == 'string') {
            return $.fn.yqFileEdit.methods[opts](this, param);
        }

        return this.each(function () {
            var $this = $(this);
            var opt;
            if ($this.data("yqtype") == "yqFileEdit") {
                // var $uniqueID = $this.attr("ID");
                // var opts_ = $.extend({}, options($this));
                // destroy($this);
                // $this = $("#" + $uniqueID);
                // opt = $.extend(opts_, opts);
            } else {
                opt = $.extend({}, $.fn.yqFileEdit.defaults, opts);
                // var $uniqueID = $this.attr("ID");
                // if ($uniqueID === undefined || $uniqueID === null || $uniqueID == "") {
                //     $uniqueID = $.getUniqueID();
                //     $this.attr("ID", $uniqueID);
                // }
            }

            if (opt.width === undefined && $this.width() > 0) {
                opt.width = $this.width();
            }
            else if (typeof opt.width != "undefined") {
                $this.width(opt.width);
            }

            if (opt.height === undefined && $this.height() > 0) {
                opt.height = $this.height();
            }
            else if (typeof opt.height != "undefined") {
                $this.height(opt.height);
            }

            if ($this[0].tagName.toLowerCase() != "textarea") {
                var $uniqueID = $this.attr("id");
                $this.removeAttr("id");
                $this.after('<textarea id="' + $uniqueID + '" style="width: ' + opt.width + 'px;height:' + opt.height + 'px;"></textarea>')
                $this.remove();
                $this = $("#" + $uniqueID);
            }

            //组件加载结束
            opt.onload = true;
            //组件进程执行中
            opt.running = false;

            //变量信息
            $this.data("yqfiledit_opt", opt);
            $this.data("yqtype", "yqFileEdit");

            var file = [];
            file.push({ url: "/scripts/crypto/sha256.min.js", type: "js" });
            $.yqLoadJsCss(file, function () {
                init_ui($this);
            })

            return $this;
        });
    };

    $.fn.yqFileEdit.defaults = {
        theme: "eclipse",
        fontSize: 14,
        data: {},
        goDocEnd: false,
        runfile: false,
        afterBindingTitle: function () { }, //标题绑定后
    };

    $.fn.yqFileEdit.methods = {
        options: function (jq) {
            return options($(jq));
        },
        resize: function (jq, params) {
            resize($(jq), params)
        }, destroy: function (jq) {
            destroy($(jq[0]));
        },
    };

    function options($object) {
        return $object.data("yqfiledit_opt");
    }

    function resize($object, params) {
        var opt = options($object);
        if (typeof params == "object") {
            opt.width = params.width;
            opt.height = params.height;
        }
        opt.$title.css({ "border-spacing": 0, scrolling: "no", height: 34, width: opt.width });
        $object.yqCodeEdit("resize", { width: opt.width, height: opt.height - 34 });
    }

    function destroy($object) {
        var opt = options($object);
        $object.yqCodeEdit("destroy");
        opt.$title.find(".theme").combobox("destroy");
        opt.$title.find(".font").combobox("destroy");
        // opt.$title.find(".search").linkbutton( 
        // opt.$title.find(".edit").switchbutton( 
        // opt.$title.find(".save").linkbutton( 
        // opt.$title.find(".reload").linkbutton( 
        // opt.$title.find(".download").linkbutton({
        opt.$title.remove();
    }

    function init_ui($object) {
        var opt = options($object);

        $object.width(opt.width);
        $object.height(opt.height - 34);

        var $title = $(`
    <table >
        <tr>
          <td align="left" style="padding: 0 0 0 2px;white-space: nowrap;"></td>
          <td align="right" style="padding: 0 2px 0 0;white-space: nowrap;"> 
                <input class="theme"/>
                <input class="font"/>   
                <input class="edit" title="edit"/>
                <a class="save" title="save"></a>
                <a class="reload" title="reload"></a>
                <a class="open" title="open file"></a>
                <a class="download" title="download"></a>
                <a class="runfile" title="run file"></a>
          </td>
        </tr>
    </table>`);
        opt.$title = $title;

        $title.css({ "border-spacing": 0, scrolling: "no", height: 34, width: opt.width });
        $object.before($title);
        $($title.find("td")[0]).html('<lable class="name">' + opt.data.name + '</lable><lable class="size">' + formatSize(opt.data.size, 2)) + '</lable>';

        var themes_ = [];
        var themes = $.fn.yqCodeEdit.defaults.themes
        for (let i = 0; i < themes.length; i++) {
            const item = themes[i];
            themes_.push({
                "id": item,
                "text": item
            });
        }
        
        var edit_theme = localStorage.getItem('easyui_edit_theme');
        if (edit_theme === null) {
            edit_theme = "eclipse";
        }
        $title.find(".theme").combobox({
            width: 150,
            label: "theme",
            labelWidth: 55,
            data: themes_,
            valueField: "id",
            textField: "text",
            value: edit_theme,
            onChange: function (newValue, oldValue) {
                localStorage.setItem('easyui_edit_theme', newValue);
                $object.yqCodeEdit("setTheme", newValue);
            }
        });
        //兼容错误字体居右
        $title.find(".theme").next().css({ "text-align": "left" });

        var filetype = getFileType(opt.data.name);
        if (filetype != "md") {
            var edit_font_size = localStorage.getItem('easyui_edit_font_size');
            if (edit_font_size === null) {
                edit_font_size = 14;
            }
            $title.find(".font").combobox({
                width: 140,
                label: "font-size",
                labelWidth: 72,
                data: [{
                    "id": 12,
                    "text": "12px"
                }, {
                    "id": 14,
                    "text": "14px"
                }, {
                    "id": 16,
                    "text": "16px"
                }, {
                    "id": 18,
                    "text": "18px"
                }, {
                    "id": 20,
                    "text": "20px"
                }, {
                    "id": 24,
                    "text": "24px"
                }, {
                    "id": 28,
                    "text": "28px"
                }, {
                    "id": 32,
                    "text": "32px"
                }],
                valueField: "id",
                textField: "text",
                value: edit_font_size,
                onChange: function (newValue, oldValue) {
                    localStorage.setItem('easyui_edit_font_size', newValue);
                    $object.yqCodeEdit("setFontSize", newValue);
                }
            });
            $title.find(".font").next().css({ "text-align": "left" });
        } else {
            $title.find(".font").remove();
        }

        $title.find(".edit").switchbutton({
            width: 60,
            checked: false,
            handleText: '<span class="yqwin-btn-icon fa fa-pencil-square-o" aria-hidden="true" style="padding: 7px;"></span>',
            onText: 'on',
            offText: "off",
            onChange: function (checked) {
                if (checked) {
                    $title.find(".open").linkbutton("enable");
                    $title.find(".save").linkbutton("enable");
                    $object.yqCodeEdit("enable");
                } else {
                    $title.find(".open").linkbutton("disable");
                    $title.find(".save").linkbutton("disable");
                    $object.yqCodeEdit("disable");
                }
            }
        });

        $title.find(".save").linkbutton({
            iconCls: 'yqwin-btn-icon fa fa-floppy-o',
            plain: false,
            disabled: true,
            onClick: function () {
                var value = $object.yqCodeEdit("getValue");
                filesave(opt.data, value, function (res) {
                    console.log("save", res);
                    if (res.error == 0) {
                        $title.find(".open").linkbutton("disable");
                        $title.find(".save").linkbutton("disable");
                        $title.find(".edit").switchbutton("uncheck");
                        $($title.find("td")[0]).html('<lable class="name">' + res.data.name + '</lable><lable class="size">' + formatSize(res.data.size, 2)) + '</lable>';
                        $.messager.show({
                            title: 'success',
                            msg: '文件已保存。',
                            timeout: 3000,
                            showType: 'show'
                        });
                    } else {
                        $.messager.alert('fail', '文件已保存失败!', 'info');
                    }
                })
            }
        });

        $title.find(".reload").linkbutton({
            iconCls: 'yqwin-btn-icon fa fa-repeat',
            plain: false,
            onClick: function () {
                $title.find(".save").linkbutton("disable");
                $title.find(".edit").switchbutton("uncheck");
                fileget(opt.data.file, function (text) {
                    $object.yqCodeEdit("setValue", text);
                    $.messager.show({
                        title: 'success',
                        msg: '文件刷新成功。',
                        timeout: 3000,
                        showType: 'show'
                    });
                });
            }
        });

        $title.find(".open").linkbutton({
            iconCls: 'yqwin-btn-icon fa fa-folder-open-o',
            plain: false,
            disabled: true,
            onClick: function () {
                var $file = $('<input type="file"></input>');
                $file.bind("change", function (event) {
                    var files = event.target.files;
                    if (files && files.length > 0) {
                        var reader = new FileReader();
                        reader.onload = function () {
                            $object.yqCodeEdit("setValue", reader.result);
                        }
                        reader.readAsText(files[0]);
                    }
                });
                $file.click();
            }
        });

        $title.find(".download").linkbutton({
            iconCls: 'yqwin-btn-icon fa fa-download',
            plain: false,
            onClick: function () {
                var data = $object.yqCodeEdit("getValue");
                let blob = new Blob([data]);
                let _url = URL.createObjectURL(blob);
                let a = document.createElement('a');
                a.setAttribute('download', opt.data.name);
                a.setAttribute('href', _url);
                a.click();
            }
        });

        //console.log(opt.data.file, opt.data.file.indexOf("yqwin/"));
        if (opt.runfile && filetype == "html") {
            $title.find(".runfile").linkbutton({
                iconCls: 'icon2-runfile',
                plain: false,
                onClick: function () {
                    window.open("/" + opt.data.file);
                }
            });
        } else {
            $title.find(".runfile").remove();
        }

        $object.yqCodeEdit({
            isEdit: false,
            theme: opt.theme,
            fontSize: opt.fontSize,
            type: filetype,
            types: [filetype],
            goDocEnd: opt.goDocEnd,
            value: "",
        });

        fileget(opt.data.file, function (text) {
            var edit_opt = $object.yqCodeEdit("options");
            $object.yqCodeEdit("setValue", text);
            opt.afterBindingTitle.call($object);
        })
    }

    function getFileType(sFileTitle) {
        let pattern = /\.{1}[A-Za-z]{1,}$/;
        let fileType01 = sFileTitle.substring(pattern.exec(sFileTitle).index + 1, sFileTitle.length);  //index是点的位置。点的位置加1再到结尾
        return fileType01;
    }

    /**
    * 格式化文件大小, 输出成带单位的字符串
    * @param {Number} size 文件大小
    * @param {Number} [pointLength=2] 精确到的小数点数。
    * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。
    *    如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.
    */
    function formatSize(size, pointLength) {
        if (pointLength === undefined) {
            pointLength = 0;
        }

        var unit;
        var units = ['B', 'K', 'M', 'G', 'TB'];
        while ((unit = units.shift()) && size > 1024) {
            size = size / 1024;
        }
        return (unit === 'B' ? size : size.toFixed(pointLength === undefined ? 2 : pointLength)) + unit;
    }

    //--文件操作 begin-----------------------------
    function fileget(fileid, callback) {
        var formData = new FormData();
        formData.append("action", "downfile");
        formData.append("file", fileid);
        $.ajax({
            type: 'POST',
            url: "_resource.html",
            data: formData,
            processData: false,
            contentType: false,
            dataType: "text",
            success: function (text) {
                callback(text);
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                console.log(XMLHttpRequest.responseText);
                callback(XMLHttpRequest.responseText);
            }
        });
    }

    function filesave(data, f_txt, callback) {
        const blob = new Blob([f_txt], { type: data.mine });
        // createObjectURL() 静态方法创建一个 DOMString，其中包含一个 URL，该 URL 表示参数中给定的对象。

        var fileFingerprint;
        var reader = new FileReader();
        reader.onload = function () {
            fileFingerprint = HashBase64(reader.result, 'SHA256');
            upload();
        }
        reader.readAsArrayBuffer(blob);

        function upload() {
            var formData = new FormData();
            formData.set('action', 'uploadfile');
            formData.set('file', blob);
            formData.set('name', data.file);
            formData.set('finger', fileFingerprint);
            $.ajax({
                type: 'post',
                url: "_resource.html",
                data: formData,
                cache: false,
                processData: false,
                contentType: false,
                dataType: 'json',
                success: function (res) {
                    if (!$.yqDataErrCheck(res)) {
                        return;
                    }

                    callback(res);
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    console.error(errorThrown);
                    callback({ error: 99, info: errorThrown });
                }
            });
        }
    }

    function HashBase64(str, protocol = 'SHA256') {
        result = str
        switch (protocol) {
            case 'MD5':
                result = String.fromCharCode(...md5.array(str))
                break;
            case 'SHA1':
                result = String.fromCharCode(...sha1.array(str))
                break;
            case 'SHA224':
                result = String.fromCharCode(...sha224.array(str))
                break;
            case 'SHA256':
                result = String.fromCharCode(...sha256.array(str))
                break;
        }
        result = btoa(result).replaceAll("\/", "_").replaceAll("+", "-");
        return result;
    }
    //--文件操作 end-------------------------------

})(jQuery);
